package designPatterns.com.course_design.scrapy.scheduler;

import designPatterns.com.course_design.scrapy.Engine;
import designPatterns.com.course_design.scrapy.http.request.Request;
import designPatterns.com.course_design.scrapy.logger.Log;
import designPatterns.com.course_design.scrapy.util.LogInjection;

import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @projectName DesignPattern
 * @className study.scrapy.Scheduler
 * @description
 */

public abstract class Scheduler extends ReentrantLock implements Runnable {
    protected volatile Queue<Request> requestQueue;
    protected Engine engine;
    @LogInjection
    protected Log log;
    private final Condition condition = this.newCondition();

    public void signalCondition() {
        this.condition.signalAll();
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public boolean isEmpty(){return requestQueue.isEmpty();}

    public boolean signal() {
        this.lock();
        boolean flag = !(this.getWaitQueueLength(condition) > 0 && this.requestQueue.isEmpty());
        this.unlock();
        return flag;
    }

    public void addRequest(Request request) {
        this.requestQueue.add(request);
        log.info("engine 发送 request 给 scheduler ,current size=" + this.requestQueue.size() + ",url=" + request.getUrl());
    }

    public Request getRequest() {
        Request request = this.requestQueue.poll();
        log.info("返回给 engine , current size = " + this.requestQueue.size() + ",url=" + request.getUrl());
        return request;
    }

    @Override
    public void run() {
        while (this.engine.isRunning()) {
            this.lock();
//            log.info("scheduler running");
            try {
                while (this.requestQueue.isEmpty() && this.engine.isRunning()) {
                    //优化，没事不占用时间片
                    condition.await();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                this.unlock();
            }
            if (this.engine.getCurrentState() == Engine.END)
                break;

            //返回Request
            Request request = getRequest();
            this.engine.getRequestFromScheduler(request);
        }
        System.out.println("=====================END OF SCHEDULER=====================");
    }
}